package com.lock.util;

import com.lock.common.FBSOrderLock;
import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

/**
 * 递归类型的有序节点分布式锁
 * Created by Administrator on 2017/7/17.
 */
public class OrderLockUtil implements Watcher {
    private ZooKeeper zooKeeper;
    private String nowPath;
    private String prePath;
    private String name;
    private final static String parentPath = "/OrderLock";
    private final static String path = "/OrderLock/sub";

    public OrderLockUtil() {
        try {
            zooKeeper = new ZooKeeper("127.0.0.1:2181",60000,this);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void process(WatchedEvent watchedEvent) {

    }

    /**
     * 入口
     * @return
     */
    public Boolean entrance(){
        name = Thread.currentThread().getName();
        caeateParentPath();
        return getLock();
    }

    /**
     * 获取锁
     * @return
     */
    private Boolean getLock() {
        nowPath = createPath(path);
        System.out.println(name+"=======创建子节点"+nowPath);
        //判断自己是不是最小节点
        return isMin();
    }

    /**
     * 当前线程节点是否是最小的
     * @return
     */
    private boolean isMin() {
        try {
            List<String> childList = zooKeeper.getChildren(parentPath,false);
            Collections.sort(childList);
            int index = childList.indexOf(nowPath.substring(parentPath.length()+1));
            switch (index){
                case -1:{
                    System.out.println(name+"=该线程节点"+path+"不存在");
                    return false;
                }
                case 0:{
                    System.out.println(name+"=该线程是老大，允许执行");
                    return true;
                }
                default:{
                    prePath = parentPath+"/"+childList.get(index-1);
                    System.out.println(name+"=获取子节点中，排在我面前的是"+prePath);
                    return isMin();
                }
            }
        } catch (KeeperException e) {
            e.printStackTrace();
            return false;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 释放资源
     */
    public void deleteLock(){
        try {
            zooKeeper.delete(nowPath,-1);
            System.out.println(name+"删除本节点："+nowPath);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            releaseConnection();
        }
    }

    private void caeateParentPath(){
        synchronized (this){
            if (createPath(parentPath,"111")){
                System.out.println(name+"=线程抢占先机创建了主节点。。。。");
            }
        }
    }

    private Boolean createPath(String path,String data){
        try {
            zooKeeper.create(path,data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            return true;
        } catch (KeeperException e) {
            return false;
        } catch (InterruptedException e) {
            return false;
        }
    }

    private String createPath(String path){
        try {
            return zooKeeper.create(path,"111".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        } catch (KeeperException e) {
            e.printStackTrace();
            return "";
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 关闭ZK连接
     */
    private void releaseConnection() {
        if ( this.zooKeeper !=null ) {
            try {
                this.zooKeeper.close();
            } catch ( InterruptedException e ) {}
        }
        System.out.println(name+"释放连接");
    }
}
